/** new 操作符 */
export const myNew = (fn: Function, ...args) => {
    // 1,创建一个空对象
    const obj = Object.create(null);

    // 2,将空对象的 __proto__ 指向构造函数的prototype
    obj.__proto__ = fn.prototype;

    // 3,将构造函数的this指向obj,并执行构造函数
    const res = fn.apply(obj, args);

    // 4,如果构造函数返回一个对象,则返回该对象,否则返回obj
    return res instanceof Object ? res : obj
}

/**  防抖 */
export const debounce = (fn: Function, delay: number) => {
    let timer = null
    return function () {
        const context = this
        const args = arguments
        if (timer) clearTimeout(timer)
        timer = setTimeout(() => {
            fn.apply(context, args)
        }, delay)
    }
}

/**  节流 */
export const throttle = (fn: Function, delay: number) => {
    let timer = null
    return function () {
        const context = this
        const args = arguments
        if (!timer) {
            timer = setTimeout(() => {
                fn.apply(context, args)
                timer = null
            }, delay)
        }
    }
}

/**  一键复制 */
export const copyText = (text: string) => {
    if (!text) {
        console.log('没有复制内容')
        return
    }
    const copy = (text: string) => {
        const input = document.createElement('input')
        document.body.appendChild(input)
        input.setAttribute('value', text)
        input.focus()
        input.select()
        document.execCommand('copy')
        document.body.removeChild(input)
    }

    if (navigator?.clipboard) {
        navigator.clipboard.writeText(text).catch((err) => copy(text))
    } else {
        copy(text)
    }
}

/**
 * @description 封装⼀个动画函数:控制⼀个数的变化.
 * 规定时间duration内从start匀速变化到target;callback在每次变化时执⾏;动画结束执⾏callback;使⽤requestAnimationFrame实现;返回⼀个终⽌动画的函数的id
 * @param {number} start 初始值
 * @param {number} target ⽬标值
 * @param {number} duration 持续时间
 * @param {function} callback 回调函数
 */
export const animation = (start: number, target: number, duration: number, callback: Function) => {
    let startTime = Date.now()

    function step() {
        let now = Date.now()
        let progress = (now - startTime) / duration
        if (progress > 1) progress = 1
        let value = start + (target - startTime) * progress
        value = value.toFixed(2)
        callback(value)
        if (progress > 1) {
            requestAnimationFrame(step)
        } else {
            return
        }
    }

    step()
}